package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageBean;
import com.zzyl.constant.Constants;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.LoginDto;
import com.zzyl.dto.PasswordDto;
import com.zzyl.dto.UserDto;
import com.zzyl.entity.*;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.*;
import com.zzyl.properties.JwtTokenProperties;
import com.zzyl.properties.SecurityProperties;
import com.zzyl.service.UserService;
import com.zzyl.utils.JwtUtil;
import com.zzyl.utils.NoProcessing;
import com.zzyl.utils.ThreadLocalUtil;
import com.zzyl.vo.LoginVo;
import com.zzyl.vo.UserVo;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户表服务实现类
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private JwtTokenProperties jwtTokenProperties;
    @Autowired
    private SecurityProperties securityProperties;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private PostMapper postMapper;

    /**
     * 后台用户登录
     *
     * @param dto 用户登录Dto
     * @return {@code LoginVo }
     * @author YiSheep
     */
    @Override
    public LoginVo login(LoginDto dto) {
        User user = userMapper.selectByUsername(dto.getUsername());
        if (ObjectUtil.isEmpty(user) || !DigestUtil.bcryptCheck(dto.getPassword(), user.getPassword())) {
            throw new BaseException(BasicEnum.INCORRECT_PASSWORD);
        }
        if (StrUtil.equals(user.getDataState(), "1")) {
            throw new BaseException(BasicEnum.ACCOUNT_DISABLED);
        }
        Map<String, Object> params = new HashMap<>();
        params.put("userid", user.getId());
        String jwt = JwtUtil.createJWT(jwtTokenProperties.getSecretKey(), jwtTokenProperties.getTtl(), params);
        LoginVo loginVo = BeanUtil.toBean(user, LoginVo.class);
        loginVo.setUserToken(jwt);
        //密码脱敏
        loginVo.setPassword("");
        return loginVo;
    }

    /**
     * 用户分页
     *
     * @param dto      用户Dto
     * @param pageNum  书籍页码
     * @param pageSize 页面大小
     * @return {@code PageBean<UserVo> }
     * @author YiSheep
     */
    @Override
    public PageBean<UserVo> pageQuery(UserDto dto, Integer pageNum, Integer pageSize) {
        if (ObjectUtil.isNotEmpty(dto.getDeptNo())) {
            //处理部门编号，提取有效位前缀   100200300000 -> 100200300
            dto.setDeptNo(NoProcessing.processString(dto.getDeptNo()));
        }

        //开启分页
        PageHelper.startPage(pageNum, pageSize);

        //调用业务层查询数据
        Page<User> page = userMapper.selectPage(dto); //只查询用户、部门、职位数据，角色数据在业务层补全（因为用户和角色是一对多关系）

        PageBean<UserVo> pageBean = PageBean.of(page, UserVo.class);

        if (CollUtil.isEmpty(pageBean.getRecords())) {
            return pageBean;
        }

        //处理每个用户对应的角色
        pageBean.getRecords().forEach(userVo -> {
            //查询对应角色
            List<Role> roleList = roleMapper.findRoleListByUserId(userVo.getId());

            //提取集合中每个Role对象的id属性
            List<String> roleVoIds = CollUtil.getFieldValues(roleList, "id", String.class);
            //提取集合中每个Role对象的roleName属性
            List<String> roleLabels = CollUtil.getFieldValues(roleList, "roleName", String.class);

            //设置角色的ids
            userVo.setRoleVoIds(Set.copyOf(roleVoIds));
            //设置角色名称
            userVo.setRoleLabels(Set.copyOf(roleLabels));
        });

        //返回数据
        return pageBean;
    }

    /**
     * 用户添加
     *
     * @param dto 用户Dto
     * @author YiSheep
     */
    @Transactional
    @Override
    public void userAdd(UserDto dto) {
        //根据部门编号查询，是否是最底层的部门，如果不是，不允许添加用户
        int count = deptMapper.isLowestDept(dto.getDeptNo());
        if (count > 0) {
            throw new BaseException(BasicEnum.USER_LOCATED_BOTTOMED_DEPT);
        }
        User user = BeanUtil.toBean(dto, User.class);
        user.setUsername(user.getEmail());
        user.setNickName(user.getRealName());
        user.setDataState(SuperConstant.DATA_STATE_0);
        user.setPassword(DigestUtil.bcrypt(securityProperties.getDefaultPassword()));
        userMapper.insert(user);
        List<UserRole> userRoleList = new ArrayList<>();
        dto.getRoleVoIds().forEach(r -> {
            userRoleList.add(UserRole.builder()
                    .userId(user.getId())
                    .roleId(Long.valueOf(r))
                    .dataState(SuperConstant.DATA_STATE_0)
                    .build());
        });
        userRoleMapper.batchInsert(userRoleList);
    }

    /**
     * 用户修改
     *
     * @param dto 用户Dto
     * @author YiSheep
     */
    @Transactional
    @Override
    public void userUpdate(UserDto dto) {
        //根据部门编号查询，是否是最底层的部门，如果不是，不允许添加用户
        int count = deptMapper.isLowestDept(dto.getDeptNo());
        if (count > 0) {
            throw new BaseException(BasicEnum.USER_LOCATED_BOTTOMED_DEPT);
        }
        User user = BeanUtil.toBean(dto, User.class);
        user.setUsername(dto.getEmail());
        userMapper.updateByPrimaryKeySelective(user);

        if (CollUtil.isEmpty(dto.getRoleVoIds())) {
            return;
        }

        userRoleMapper.deleteUserRoleByUserId(user.getId());
        dto.getRoleVoIds().forEach(roleVoId -> {
            UserRole userRole = UserRole.builder()
                    .userId(user.getId())
                    .roleId(Long.valueOf(roleVoId))
                    .dataState(SuperConstant.DATA_STATE_0)
                    .build();
            userRoleMapper.insert(userRole);
        });
    }

    /**
     * 删除用户
     *
     * @param userIds 用户ID
     * @author YiSheep
     */
    @Transactional
    @Override
    public void userDelete(Long userIds) {
        userMapper.deleteByPrimaryKey(userIds);
        userRoleMapper.deleteUserRoleByUserId(userIds);
    }

    /**
     * 启用或禁用用户
     *
     * @param id     用户ID
     * @param status 状态
     * @author YiSheep
     */
    @Override
    public void enableOrDisable(Long id, String status) {
        User user = User.builder()
                .id(id)
                .dataState(status)
                .build();
        userMapper.updateByPrimaryKeySelective(user);
    }

    /**
     * 用户列表
     *
     * @param dto 用户Dto
     * @return {@code UserVo }
     * @author YiSheep
     */
    @Override
    public List<UserVo> list(UserDto dto) {
        List<User> users = userMapper.selectList();
        List<UserVo> userVoList = BeanUtil.copyToList(users, UserVo.class);
        return userVoList;
    }

    /**
     * 密码重置
     *
     * @param userId 用户id
     * @author YiSheep
     */
    @Override
    public void resetPasswords(Long userId) {
        User user = User.builder()
                .id(userId)
                .password(DigestUtil.bcrypt(securityProperties.getDefaultPassword()))
                .build();
        userMapper.updateByPrimaryKeySelective(user);
    }

    /**
     * 密码校验
     *
     * @param dto 密码Dto
     * @author YiSheep
     */
    @Override
    public void cmodifyPasswords(PasswordDto dto) {
        Long id = ThreadLocalUtil.get();
        User user = userMapper.selectByPrimaryKey(id);
        if (!DigestUtil.bcryptCheck(dto.getOldPw(), user.getPassword())) {
            throw new RuntimeException("原始密码不正确");
        }
    }

    /**
     * 个人信息
     *
     * @return {@code UserVo }
     * @author YiSheep
     */
    @Override
    public UserVo getCurrentUser() {
        Long id = ThreadLocalUtil.get();
        User user = userMapper.selectByPrimaryKey(id);
        UserVo userVo = BeanUtil.toBean(user, UserVo.class);

        List<Role> roleList = roleMapper.findRoleListByUserId(userVo.getId());
        Set<String> roleNames = roleList.stream().map(role -> role.getRoleName()).collect(Collectors.toSet());
        userVo.setRoleNames(roleNames);


        Dept dept = deptMapper.selectByDeptNo(user.getDeptNo());
        userVo.setDeptName(dept.getDeptName());

        Post post = postMapper.selectByPostNo(user.getPostNo());
        userVo.setPostName(post.getPostName());

        return userVo;
    }

    /**
     * 修改密码
     *
     * @param dto 密码dto
     * @author YiSheep
     */
    @Override
    public void modifyPasswords(PasswordDto dto) {
        Long id = ThreadLocalUtil.get();
        User user = userMapper.selectByPrimaryKey(id);
        user.setPassword(DigestUtil.bcrypt(dto.getPw()));
        userMapper.updateByPrimaryKeySelective(user);
    }
}
